package com.example.demo.common;


import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import java.util.Collection;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;

@ApiModel(value = "ApiResult", description = "统一返回对象")
public class ApiResult<T> {
    public final static int SUCCESS = 200;

    @ApiModelProperty(value = "表示Response信息成功", dataType = "int")
    private int status;

    @ApiModelProperty(value = "返回码", dataType = "string")
    private String errorMsg;

    private String content;

    @ApiModelProperty(value = "返回数值")
    private T data;


    public ApiResult() {
    }

    private ApiResult(int status, T data, String errorMsg) {
        this.status = status;
        this.data = data;
        this.errorMsg = errorMsg;
    }

    private ApiResult(int status, T data, String errorMsg, String content) {
        this.status = status;
        this.data = data;
        this.errorMsg = errorMsg;
        this.content = content;
    }

    //================================构造方法================================================
    public static <T> ApiResult<T> ok() {
        return new ApiResult<>(SUCCESS, null, null);
    }

    public static <T> ApiResult<T> ok(T data) {
        return new ApiResult<>(SUCCESS, data, null);
    }

    public static <T> ApiResult<T> ok(T data, String content) {
        return new ApiResult<>(SUCCESS, data, null, content);
    }

    public static <T> ApiResult<T> error(int status, String errorMsg) {
        return new ApiResult<>(status, null, errorMsg);
    }

    public static <T> ApiResult<T> error(int status, String errorMsg, String content) {
        return new ApiResult<>(status, null, errorMsg, content);
    }

    public static <T> ApiResult<T> error(int status, String errorMsg, T data) {
        return new ApiResult<>(status, data, errorMsg);
    }

    public static <T> ApiResult<T> error(GetErrorMessage getErrorMessage) {
        return new ApiResult<>(getErrorMessage.getStatus(), null, getErrorMessage.getMessage());
    }

    public static <T> ApiResult<T> error(ApiResult<?> result) {
        return new ApiResult<>(result.getStatus(), null, result.getErrorMsg());
    }

    public static <T> ApiResult<T> error(GetErrorMessage getErrorMessage, T data) {
        return new ApiResult<>(getErrorMessage.getStatus(), data, getErrorMessage.getMessage());
    }

    //=================================================
    public <U> ApiResult<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (isFailure()) {
            return ApiResult.error(this.status, this.errorMsg);
        } else {
            return ApiResult.ok(mapper.apply(this.data));
        }
    }

    public void ifSuccess(Consumer<ApiResult<T>> consumer) {
        Objects.requireNonNull(consumer);

        if (isSuccess()) {
            consumer.accept(this);
        }
    }

    public void ifPresent(Consumer<ApiResult<T>> consumer) {
        Objects.requireNonNull(consumer);

        if (isPresent()) {
            consumer.accept(this);
        }
    }

    public boolean isSuccess() {
        return SUCCESS == status;
    }

    public boolean isFailure() {
        return !isSuccess();
    }

    public boolean isPresent() {
        return isSuccess() && (data != null && isNotEmpty());
    }

    private boolean isNotEmpty() {
        if (data instanceof Collection) {
			return ((Collection) data).size() > 0;
        }
        return true;
    }


    public int getStatus() {
        return status;
    }

    public ApiResult<T> setStatus(int status) {
        this.status = status;
        return this;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public ApiResult<T> setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
        return this;
    }

    public T getData() {
        return data;
    }

    public ApiResult<T> setData(T data) {
        this.data = data;
        return this;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "ApiResult{" +
                "status=" + status +
                ", errorMsg='" + errorMsg + '\'' +
                ", data=" + data +
                '}';
    }
}
